package list

import "fmt"

type node[V any] struct {
	data V
	next *node[V]
}

type LinkedList[V any] struct {
	head *node[V]
}

func (l *LinkedList[V]) Add(val V) {
	if l.head == nil {
		l.head = &node[V]{
			data: val,
		}
		return
	}
	current := l.head
	for {
		if current.next == nil {
			current.next = &node[V]{
				data: val,
			}
			return
		}
		current = current.next
	}
}

func (l *LinkedList[V]) Insert(index int, val V) {
	n := &node[V]{
		data: val,
	}
	if index == 0 {
		n.next = l.head
		l.head = n
		return
	}
	current := l.head
	for i := 1; i < index; i++ {
		current = current.next
	}
	n.next = current.next
	current.next = n
}

func (l *LinkedList[V]) RemoveByIndex(index int) bool {
	if l.head == nil || index < 0 {
		return false
	}
	if index == 0 {
		l.head = l.head.next
		return true
	}
	current := l.head
	for i := 1; i < index; i++ {
		if current.next == nil {
			return false
		}
		current = current.next
	}
	current.next = current.next.next
	return true
}

func (l *LinkedList[V]) GetByIndex(index int) (V, error) {
	current := l.head
	for i := 0; i < index; i++ {
		if current.next == nil {
			return node[V]{}.data, fmt.Errorf("index out")
		}
		current = current.next
	}
	return current.data, nil
}
